/**
 * Copyright (C), 2017-2018, XXX有限公司
 * FileName: AioServer
 * Author:   zengjian
 * Date:     2018/9/16 10:02
 * Description: 服务端
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package fun.codedesign.jdk.socket.aio;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.HashMap;
import java.util.Map;

/**
 * 〈服务端〉<br>
 * 〈一句话描述〉
 *
 * @author zengjian
 * @create 2018/9/16 10:02
 */
public class AioServer {

    private AsynchronousServerSocketChannel channel;

    public AioServer() {
        try {
            channel = AsynchronousServerSocketChannel.open();
            channel.bind(new InetSocketAddress(8080));
            System.out.println("aio server start:8080");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        channel.accept(this, new ServerHandler());
    }

    class ServerHandler implements CompletionHandler<AsynchronousSocketChannel, AioServer> {

        @Override
        public void completed(final AsynchronousSocketChannel socketChannel, final AioServer aioServer) {
            // 递归接收别的请求
            aioServer.channel.accept(aioServer, this);
            final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
            socketChannel.read(byteBuffer, byteBuffer, new CallbackHandler(socketChannel));
        }

        @Override
        public void failed(Throwable exc, AioServer attachment) {
            System.err.println(exc);
        }
    }

    class CallbackHandler implements CompletionHandler<Integer, ByteBuffer>{

        private final AsynchronousSocketChannel socketChannel;

        public CallbackHandler(AsynchronousSocketChannel socketChannel) {
            this.socketChannel = socketChannel;
        }

        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            // 写入或者读取后要重新操作都需要flip一下
            attachment.flip();
            byte[] bytes = new byte[attachment.remaining()];
            attachment.get(bytes);
            try {
                String req = new String(bytes, "utf-8");
                System.out.println("接收到请求:" + req);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // 返回消息
            ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
            try {
                writeBuffer.put("aio accept your message".getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            writeBuffer.flip();
            socketChannel.write(writeBuffer);
        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            System.err.println(exc);
        }
    }

    public static void main(String[] args) throws IOException {
        AioServer server = new AioServer();
        server.start();
        System.in.read();
        Map<String, String> map = new HashMap<>();
        Integer a = new Integer(123);
        System.out.println(map);
        System.out.println(a);
    }
}